package com.xht.filter;

import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Component
public class SensitiveFilter {
    // 使用DFA算法结构
    private final Map<Object, Object> dfaMap = new HashMap<>();

    // 加载敏感词文件
    @PostConstruct //会在创建实例化后自动执行该方法
    public void init() {
        try {
            ClassPathResource resource = new ClassPathResource("sensitive-words.txt");//解析该相对路径下的文件 并生成类对象
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8));//先转换为流对象
            //再生成BufferedReader对象

            String keyword;
            while ((keyword = reader.readLine()) != null) { //一行一行 遍历
                addKeyword(keyword.trim()); //构建DFA树
            }
            reader.close();//流对象关闭
        } catch (IOException e) {
            throw new RuntimeException("加载敏感词文件失败", e);
        }
    }

    // 构建DFA树
    private void addKeyword(String keyword) {
        Map<Object, Object> currentMap = dfaMap; //其中dfaMap为全局变量
        for (int i = 0; i < keyword.length(); i++) {
            char c = keyword.charAt(i);
            Map<Object, Object> subMap = (Map<Object, Object>) currentMap.get(c);
            if (subMap == null) {
                subMap = new HashMap<>();
                currentMap.put(c, subMap);
            }
            currentMap = subMap;

            // 设置结束标识
            if (i == keyword.length() - 1) {
                currentMap.put("isEnd", true);
            }
        }
    }

    // 检查文本是否包含敏感词
    public boolean containsSensitive(String text) {
        text = text.toLowerCase(); // 统一小写处理
        for (int i = 0; i < text.length(); i++) {
            int matchLength = checkSensitiveWord(text, i);
            if (matchLength > 0) {
                return true;
            }
        }
        return false;
    }

    private int checkSensitiveWord(String text, int beginIndex) {
        boolean flag = false;
        int matchLength = 0;
        Map<Object, Object> tempMap = dfaMap;

        for (int i = beginIndex; i < text.length(); i++) {
            char c = text.charAt(i);
            tempMap = (Map<Object, Object>) tempMap.get(c);

            if (tempMap == null) {
                break;
            } else {
                matchLength++;
                if (tempMap.containsKey("isEnd")) {
                    flag = true;
                }
            }
        }
        return flag ? matchLength : 0;
    }
}
